home *** CD-ROM | disk | FTP | other *** search
- ///////////////////////////////////////////////////////////////////////////////
- // $Id: Interface.cxx,v 1.4 1995/01/15 22:45:49 bmott Exp $
- ///////////////////////////////////////////////////////////////////////////////
- // Interface.cxx
- //
- // This is the user interface command class. It handles all of the
- // command's issue by the user interface.
- //
- //
- // BSVC "A Microprocessor Simulation Framework"
- // Copyright (c) 1993
- // By: Bradford W. Mott
- // October 21,1993
- //
- ///////////////////////////////////////////////////////////////////////////////
- // $Log: Interface.cxx,v $
- // Revision 1.4 1995/01/15 22:45:49 bmott
- // Had to cast the signal handler function
- //
- // Revision 1.3 1995/01/13 00:29:21 bmott
- // Changed all of the variable size arrays to be a fixed size to
- // conform to ansi C++ standards
- //
- // Revision 1.2 1995/01/01 03:46:51 bmott
- // Changed the ListMemory command
- //
- // Revision 1.1 1994/08/03 22:54:11 bmott
- // Initial revision
- //
- //
- ///////////////////////////////////////////////////////////////////////////////
-
- #include "Interface.hxx"
- #include "Tools.hxx"
-
- #include <unistd.h>
- #include <signal.h>
- #include <String.h>
- #include <iostream.h>
- #include <stdio.h>
- #include <string.h>
-
- char *Interface::Get()
- {
- char *command;
-
- command=new char[4096];
- gets(command);
-
- return(command);
- }
-
- void Interface::Put(const char *s)
- {
- String tmp(s);
-
- tmp+="\n";
- write(1,(char*)tmp,tmp.length());
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- // Simulator's main loop, Gets a command from the UI, parses and executes it.
- ///////////////////////////////////////////////////////////////////////////////
- void Interface::CommandLoop()
- {
- char *command;
-
- Put("BSVC Simulator");
-
- while(1)
- {
- Put("Ready!"); // Prompt the user interface
- command=Get(); // Get the next command from the UI
-
- if(ExecuteCommand(command))
- {
- delete[] command;
- break;
- }
- else
- {
- delete[] command;
- }
- }
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- // Parse and execute the given command
- ///////////////////////////////////////////////////////////////////////////////
- int Interface::ExecuteCommand(const char *command)
- {
- if(strcmp(command,"Exit")==0)
- return(1);
-
- for(int t=0;t<number_of_commands;++t)
- {
- unsigned int length = strlen(command_table[t].name);
- if(strncmp(command_table[t].name, command, length ) == 0)
- {
- (this->*command_table[t].mfp)((char*)&command[length]);
- return(0);
- }
- }
- Put("ERROR: Unknown command!");
- return(0);
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- // The user interface command table
- ///////////////////////////////////////////////////////////////////////////////
- UICommandTable Interface::command_table[] = {
- {"AddBreakpoint", &Interface::AddBreakpoint},
- {"AttachDevice", &Interface::AttachDevice},
- {"ClearStatistics", &Interface::ClearStatistics},
- {"DetachDevice", &Interface::DetachDevice},
- {"DeleteBreakpoint", &Interface::DeleteBreakpoint},
- {"ListAttachedDevices", &Interface::ListAttachedDevices},
- {"ListBreakpoints", &Interface::ListBreakpoints},
- {"ListDevices", &Interface::ListDevices},
- {"ListDeviceScript", &Interface::ListDeviceScript},
- {"ListExecutionTraceRecord", &Interface::ListExecutionTraceRecord},
- {"ListDefaultExecutionTraceEntries", &Interface::ListDefaultExecutionTraceEntries},
- {"ListGranularity", &Interface::ListGranularity},
- {"ListMemory", &Interface::ListMemory},
- {"ListMaximumAddress", &Interface::ListMaximumAddress},
- {"ListNumberOfAddressSpaces", &Interface::ListNumberOfAddressSpaces},
- {"ListPCRegisterName", &Interface::ListPCRegisterName},
- {"ListRegisters", &Interface::ListRegisters},
- {"ListRegisterValue", &Interface::ListRegisterValue},
- {"ListRegisterDescription", &Interface::ListRegisterDescription},
- {"ListStatistics", &Interface::ListStatistics},
- {"LoadProgram", &Interface::LoadProgram},
- {"Reset", &Interface::Reset},
- {"Run", &Interface::Run},
- {"SetMemory", &Interface::SetMemory},
- {"SetRegister", &Interface::SetRegister},
- {"Step", &Interface::Step}
- };
-
- ///////////////////////////////////////////////////////////////////////////////
- // Global flag to indicate an interrupt signal occurance
- ///////////////////////////////////////////////////////////////////////////////
- int Interface::interrupt_signal_flag=0;
-
- ///////////////////////////////////////////////////////////////////////////////
- // Interrupt signal handler
- ///////////////////////////////////////////////////////////////////////////////
- void Interface::InterruptSignalHandler(int arg)
- {
- Interface::interrupt_signal_flag=1;
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- // The constructor for UICommand objects
- ///////////////////////////////////////////////////////////////////////////////
- Interface::Interface(BasicCPU* c, BasicDeviceRegistry* r, BasicLoader* l)
- : number_of_commands(sizeof(command_table) / sizeof(UICommandTable)),
- cpu((BasicCPU* const)c),
- device_registry((BasicDeviceRegistry* const)r),
- loader((BasicLoader* const)l)
- {
- // Setup the Interrupt signal handler
- struct sigaction newsig,oldsig;
-
- sigaction(SIGINT, (void*)0, &newsig);
- #ifdef __linux__
- newsig.sa_handler=&Interface::InterruptSignalHandler;
- #elif _HPUX_SOURCE
- newsig.sa_handler=&Interface::InterruptSignalHandler;
- #else
- newsig.sa_handler=(void(*)(void))&Interface::InterruptSignalHandler;
- #endif
- newsig.sa_flags=0;
- sigaction(SIGINT, &newsig, &oldsig);
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- // Print the name of the Program Counter register
- ///////////////////////////////////////////////////////////////////////////////
- void Interface::ListPCRegisterName(char*)
- {
- Put(cpu->NameOfProgramCounter());
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- // List the processor's execution trace record
- ///////////////////////////////////////////////////////////////////////////////
- void Interface::ListExecutionTraceRecord(char *)
- {
- Put(cpu->ExecutionTraceRecord());
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- // List the processor's default execution trace entries to display
- ///////////////////////////////////////////////////////////////////////////////
- void Interface::ListDefaultExecutionTraceEntries(char *)
- {
- Put(cpu->DefaultExecutionTraceEntries());
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- // Clear the cpu's statistics
- ///////////////////////////////////////////////////////////////////////////////
- void Interface::ClearStatistics(char *)
- {
- cpu->ClearStatistics();
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- // List the cpu's statistics
- ///////////////////////////////////////////////////////////////////////////////
- void Interface::ListStatistics(char *)
- {
- StatisticalInformationList list(cpu);
-
- for(int t=0;t<list.NumberOfElements();++t)
- {
- StatisticInformation info;
- list.Element(t,info);
- Put(info.Statistic());
- }
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- // List the cpu's registers
- ///////////////////////////////////////////////////////////////////////////////
- void Interface::ListRegisters(char *)
- {
- int t, max_width;
- RegisterInformationList list(cpu);
-
- // Find the widest register name
- for(max_width=0,t=0;t<list.NumberOfElements();++t)
- {
- RegisterInformation info;
- list.Element(t,info);
-
- int l=strlen(info.Name());
- if(max_width < l)
- max_width=l;
- }
-
- // send the register list to the user interface
- for(t=0;t<list.NumberOfElements();++t)
- {
- RegisterInformation info;
- list.Element(t,info);
-
- char *string=new char[max_width+strlen(info.HexValue())+3+1];
-
- strcpy(string,info.Name());
- for(int s=strlen(string);s<max_width;++s)
- string[s]=' ';
- string[max_width]='\0';
- strcat(string," = ");
- strcat(string,info.HexValue());
-
- Put(string);
- }
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- // List a register's description
- ///////////////////////////////////////////////////////////////////////////////
- void Interface::ListRegisterDescription(char *arg)
- {
- RegisterInformationList list(cpu);
- char name[256];
- int t;
-
- sscanf(arg,"%s",name);
-
- for(t=0;t<list.NumberOfElements();++t)
- {
- RegisterInformation info;
-
- list.Element(t,info);
- if(strcmp(name,info.Name())==0)
- {
- Put(info.Description());
- return;
- }
- }
- Put("ERROR: Invalid register name!");
- }
-
-
- ///////////////////////////////////////////////////////////////////////////////
- // Set one of the cpu's registers to the given value
- ///////////////////////////////////////////////////////////////////////////////
- void Interface::SetRegister(char *arg)
- {
- RegisterInformationList list(cpu);
- char name[256];
- char value[256];
- int t;
-
- if(sscanf(arg,"%s %s",name,value)!=2)
- {
- Put("ERROR: Invalid arguments!");
- }
- else
- {
- for(t=0;t<list.NumberOfElements();++t)
- {
- RegisterInformation info;
-
- list.Element(t,info);
- if(strcmp(name,info.Name())==0)
- {
- cpu->SetRegister(name,value);
- return;
- }
- }
- Put("ERROR: Invalid register name!");
- }
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- // List the value of one of the cpu's registers to the given value
- ///////////////////////////////////////////////////////////////////////////////
- void Interface::ListRegisterValue(char *arg)
- {
- RegisterInformationList list(cpu);
- char name[256];
- int t;
-
- if(sscanf(arg,"%s",name)!=1)
- {
- Put("ERROR: Invalid arguments!");
- }
- else
- {
- for(t=0;t<list.NumberOfElements();++t)
- {
- RegisterInformation info;
-
- list.Element(t,info);
- if(strcmp(name,info.Name())==0)
- {
- Put(info.HexValue());
- return;
- }
- }
- Put("ERROR: Invalid register name!");
- }
- }
-
-
- ///////////////////////////////////////////////////////////////////////////////
- // Detach a device from the simulator
- ///////////////////////////////////////////////////////////////////////////////
- void Interface::DetachDevice(char *arg)
- {
- unsigned int addr_space;
- unsigned int device_index;
-
- if(sscanf(arg,"%d %d",&addr_space,&device_index)!=2)
- {
- Put("ERROR: Invalid arguments!");
- }
- else
- {
- if(addr_space>=cpu->NumberOfAddressSpaces())
- {
- Put("ERROR: Invalid address space!");
- return;
- }
-
- if(cpu->address_space[addr_space].DetachDevice(device_index)==0)
- {
- Put("ERROR: Couldn't detach device!");
- }
- }
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- // Attach a device to the simulator
- ///////////////////////////////////////////////////////////////////////////////
- void Interface::AttachDevice(char *arg)
- {
- unsigned int addr_space;
- char name[256];
- String device_args;
-
- String args(arg);
- device_args=args.after('{');
- device_args=device_args.before('}');
- if(sscanf(arg,"%d %s", &addr_space, name)!=2)
- {
- Put("ERROR: Invalid arguments!");
- }
- else
- {
- if(addr_space >= cpu->NumberOfAddressSpaces())
- {
- Put("ERROR: Invalid address space!");
- return;
- }
-
- BasicDevice *device;
- String deviceName(name);
- if(device_registry->Create(deviceName, device_args, cpu, device))
- {
- cpu->address_space[addr_space].AttachDevice(device);
- }
- else
- {
- Put("ERROR: Couldn't create the device!");
- }
- }
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- // Add a breakpoint
- ///////////////////////////////////////////////////////////////////////////////
- void Interface::AddBreakpoint(char *arg)
- {
- unsigned long address;
-
- if(sscanf(arg,"%lx",&address)!=1)
- {
- Put("ERROR: Invalid arguments!");
- }
- else
- {
- breakpoint_list.Add(address);
- }
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- // Delete a breakpoint
- ///////////////////////////////////////////////////////////////////////////////
- void Interface::DeleteBreakpoint(char *arg)
- {
- unsigned long address;
-
- if(sscanf(arg,"%lx",&address)!=1)
- {
- Put("ERROR: Invalid arguments!");
- }
- else
- {
- if(!breakpoint_list.Delete(address))
- Put("ERROR: Couldn't delete breakpoint!");
- }
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- // List the breakpoints
- ///////////////////////////////////////////////////////////////////////////////
- void Interface::ListBreakpoints(char *arg)
- {
- String breakpoint;
- unsigned long address;
-
- for(int t=0;t<breakpoint_list.NumberOfBreakpoints();++t)
- {
- breakpoint_list.GetBreakpoint(t,address);
- breakpoint=IntToString(address,8);
- Put(breakpoint);
- }
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- // List the devices attached to the simulator
- ///////////////////////////////////////////////////////////////////////////////
- void Interface::ListAttachedDevices(char *arg)
- {
- unsigned int addr_space;
-
- if(sscanf(arg,"%d",&addr_space)!=1)
- {
- Put("ERROR: Invalid arguments!");
- }
- else
- {
- if(addr_space>=cpu->NumberOfAddressSpaces())
- {
- Put("ERROR: Invalid address space!");
- return;
- }
-
- for(int t=0;t<cpu->address_space[addr_space].NumberOfAttachedDevices();++t)
- {
- String s;
-
- AddressSpaceDeviceInformation info;
- cpu->address_space[addr_space].GetDeviceInformation(t,info);
-
- s=info.name;
- s+=" {";
- s+=info.initialization_arguments;
- s+="}";
- Put(s);
- }
- }
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- // List the devices in the simulator
- ///////////////////////////////////////////////////////////////////////////////
- void Interface::ListDevices(char *)
- {
- int t;
-
- for(t=0;t<device_registry->NumberOfDevices();++t)
- {
- DeviceInformation info;
- device_registry->Information(t,info);
-
- char *string = new char[strlen(info.name)+strlen(info.description)+4+1];
- strcpy(string,info.name);
-
- Put(string);
- delete[] string;
- }
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- // List the UI script for the named device
- ///////////////////////////////////////////////////////////////////////////////
- void Interface::ListDeviceScript(char *arg)
- {
- char name[256];
-
- if (sscanf(arg,"%s",name)!=1)
- {
- Put("ERROR: Invalid arguments!");
- }
- else
- {
- for(int t=0;t<device_registry->NumberOfDevices();++t)
- {
- DeviceInformation info;
- device_registry->Information(t,info);
-
- if(strcmp(info.name,name)==0)
- {
- Put(info.script);
- return;
- }
- }
- Put("ERROR: Invalid device name!");
- }
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- // List a memory block
- ///////////////////////////////////////////////////////////////////////////////
- void Interface::ListMemory(char* arg)
- {
- unsigned int addr_space;
- unsigned long address;
- unsigned int length;
- unsigned int wordsPerLine;
- String line;
-
- if(sscanf(arg,"%x %x %x %x",&addr_space,&address,&length,&wordsPerLine) != 4)
- {
- Put("ERROR: Invalid arguments!");
- }
- else
- {
- if(addr_space >= cpu->NumberOfAddressSpaces())
- {
- Put("ERROR: Invalid address space!");
- return;
- }
-
- line = "";
- int numberOfWords = 0;
- for(int t = 0; t < length; ++t)
- {
- for(int s=0; s < cpu->Granularity(); ++s)
- {
- unsigned char value;
- if(cpu->address_space[addr_space].Peek((address+t)*cpu->Granularity()+s,
- value))
- {
- line += IntToString(value,2);
- }
- else
- {
- line += "xx";
- }
- }
- ++numberOfWords;
- if(numberOfWords >= wordsPerLine)
- {
- Put(line);
- numberOfWords = 0;
- line = "";
- }
- else
- {
- line += " ";
- }
- }
- if(line != "")
- Put(line);
- }
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- // Perform a Step of instructions
- ///////////////////////////////////////////////////////////////////////////////
- void Interface::Step(char* arg)
- {
- int number_of_steps;
-
- if(sscanf(arg,"%x", &number_of_steps)!=1)
- {
- Put("ERROR: Invalid arguments!");
- }
- else
- {
- for(int t=0;t<number_of_steps;++t)
- {
- String trace_record;
- const char* message;
-
- trace_record="";
- if((message=cpu->ExecuteInstruction(trace_record,1)) != (void*)0)
- {
- String reason("{SimulatorMessage {");
- reason+=message;
- reason+="}}";
- Put(reason);
- break;
- }
- Put(trace_record);
- }
- }
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- // Preform the Reset command
- ///////////////////////////////////////////////////////////////////////////////
- void Interface::Reset(char* arg)
- {
- // Reset the CPU (which should also reset the devices)
- cpu->Reset();
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- // Perform the Run command
- ///////////////////////////////////////////////////////////////////////////////
- void Interface::Run(char* arg)
- {
- String trace_record;
-
- // Clear the interrupt flag (Set by SIGINT)
- interrupt_signal_flag=0;
-
- // Run until something stops us!!!
- while(1)
- {
- const char *message;
-
- if((message=cpu->ExecuteInstruction(trace_record,0)) != (char*)0)
- {
- String reason("Execution stopped: ");
- reason+=message;
- Put(reason);
- break;
- }
- else if(breakpoint_list.Check(cpu->ValueOfProgramCounter()))
- {
- Put("Execution stopped at a breakpoint!");
- break;
- }
- else if(interrupt_signal_flag)
- {
- Put("Execution interrupted!");
- break;
- }
- }
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- // List the Maximum Address allow by the give address space
- ///////////////////////////////////////////////////////////////////////////////
- void Interface::ListMaximumAddress(char* arg)
- {
- unsigned int addr_space;
- unsigned long max;
- char buffer[40];
-
- if(sscanf(arg,"%x", &addr_space)!=1)
- {
- Put("ERROR: Invalid arguments!");
- }
- else
- {
- if(addr_space>=cpu->NumberOfAddressSpaces())
- {
- Put("ERROR: Invalid address space!");
- return;
- }
-
- max=cpu->address_space[addr_space].MaximumAddress();
-
- sprintf(buffer,"%x",max);
- Put(buffer);
- }
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- // List the number of address spaces for the cpu
- ///////////////////////////////////////////////////////////////////////////////
- void Interface::ListNumberOfAddressSpaces(char*)
- {
- char buffer[80];
-
- sprintf(buffer,"%d",cpu->NumberOfAddressSpaces());
- Put(buffer);
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- // List the granularity of the cpu
- ///////////////////////////////////////////////////////////////////////////////
- void Interface::ListGranularity(char*)
- {
- char buffer[80];
-
- sprintf(buffer,"%d",cpu->Granularity());
- Put(buffer);
- }
-
-
- ///////////////////////////////////////////////////////////////////////////////
- // Set a memory location to the given value
- ///////////////////////////////////////////////////////////////////////////////
- void Interface::SetMemory(char *arg)
- {
- unsigned int addr_space;
- unsigned long address;
- char value[256];
-
- if(sscanf(arg,"%d %x %s",&addr_space,&address,value)!=3)
- {
- Put("ERROR: Invalid arguments!");
- }
- else
- {
- if(addr_space>=cpu->NumberOfAddressSpaces())
- {
- Put("ERROR: Invalid address space!");
- return;
- }
- if (address > cpu->address_space[addr_space].MaximumAddress())
- {
- Put("ERROR: Invalid address!");
- return;
- }
-
- address *= cpu->Granularity();
- for(int t=0;t<cpu->Granularity();++t)
- {
- String val(value);
- cpu->address_space[addr_space].Poke(address+t,StringToInt(val(t*2,2)));
- }
- }
- }
-
-
- ///////////////////////////////////////////////////////////////////////////////
- // Load the named program into the address space
- ///////////////////////////////////////////////////////////////////////////////
- void Interface::LoadProgram(char *arg)
- {
- unsigned int addr_space;
- char name[256];
- String error;
-
- if(sscanf(arg,"%d %s",&addr_space,name)!=2)
- {
- Put("ERROR: Invalid arguments!");
- }
- else
- {
- error=loader->Load(name,addr_space);
-
- Put(error);
- }
- }
-